/*
visqrt
Copyright (C) 2010  Bhupendra Aole

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
*/

/*
 * File: Sphere.java
 * Author: Bhupendra Aole
 * Date: 30-sep-06
 */

package aole.object;

import aole.math.Color3;
import aole.math.Vec3;

public class Sphere extends Renderable {
	// sphere intersections count
	public static int count = 0;

	public Vec3 center;
	private float radius;
	// Radius square, precalculated for faster processing.
	private float sqRad;

	public Sphere() {
		this(new Vec3(), 0f);
	}

	public Sphere(float r) {
		this(new Vec3(), r);
	}

	public Sphere(Vec3 c, float r) {
		this(c, r, Color3.getRandom());
	}

	public Sphere(Vec3 c, float r, Color3 col) {
		center = c;
		radius = r;
		sqRad = r * r;
		color = col;
	}

	public void setCenter (float x, float y, float z) {
		center.set(x, y, z);
	}

	public void setCenter (Vec3 v) {
		center = v;
	}

	public void setRadius (float r) {
		radius = r;
		sqRad = r * r;
	}

	public float calcIntersection2 (Vec3 p, Vec3 d) {
		count++;
		Vec3 dst = p.getSubtracted(center);

		float A = Vec3.dot(d, d);
		float B = Vec3.dot(dst, d);
		float C = Vec3.dot(dst, dst) - sqRad;
		float D = B * B - 4f * A * C;

		if (D <= 0f)
			return -1f;

		return (float) -((B + Math.sqrt(D)) / 2f * A);
	}

	@Override
	public float calcIntersection (Vec3 p, Vec3 d) {
		count++;
		Vec3 v = p.getSubtracted(center);

		float dv = Vec3.dot(d, v);
		float d2 = Vec3.dot(d, d);
		float sq = dv * dv - d2 * (Vec3.dot(v, v) - sqRad);

		if (sq <= 0)
			return -1f;

		sq = (float) Math.sqrt(sq);
		float t1 = (-dv + sq) / d2;
		float t2 = (-dv - sq) / d2;
		if (t1 < 0)
			return t2;
		if (t2 < 0)
			return t1;
		return (t1 < t2 ? t1 : t2);
	}

	@Override
	public Vec3 getNormal (Vec3 ip) {
		return ip.getSubtracted(center).getDivided(radius);
	}

	@Override
	public String toString () {
		return "Sphere:<" + center.x + "," + center.y + "," + center.z + ">,"
				+ radius + ",<" + color.r + "," + color.g + "," + color.b + ">";
	}
}